﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.UI;
using DG.Tweening;
//using GoogleMobileAds.Api;
using MoreMountains.NiceVibrations;
using DG.Tweening.Core.Easing;
using System;
using UnityEngine.Playables;

public class MainController : BaseController {

    [Header("")]
    public Sprite[] sliceCollection;

    [Header("")]
    public GameObject collectionItemPrefab;
    public ScrollRect collectionScrollRect;
    public Transform centerTr, comingUpTr;
    public Slice[] slicePrefabs, comingSlicePrefabs;
    public Slot[] slots;
    public GameObject sliceExplosion;
    public Text scoreText;
    public Image progressImage, clockImage, circle1, circle2;
    public GameObject outofMoveObj, levelCompleteObj, pauseScreenObj, homeScreenObj, collectionScreen, sliceUnlockedScene;
    public GameObject continueObj;
    public Text continueText, currentLevelText, nextLevelText;
    public Color continueTextFrom, continueTextTo;
    public Color progressColor;
    public Image soundIcon, vibrateIcon, soundIconHome, vibrateIconHome;
    public Sprite soundOn, soundOff, vibrateOn, vibrateOff;
    public AudioSource audioSource;
    public AudioClip addToSlotClip, explosionClip, buttonClip;
    public Ease textEase;

    private int fullScore;
    private float clockTime;
    private const float CLOCK_FULL_TIME = 5;
    private bool continueClick, sliceItemClickToUnlock;
    private int justUnlockedSlice, sliceItemIndexClickToUnlock;
    private int numWatchAdToContinue;

    [HideInInspector]
    public Turn currentTurn, nextTurn;
    [HideInInspector]
    public Slice currentSlice, nextSlice;
    [HideInInspector]
    public Sprite currentSliceSprite;

    [HideInInspector]
    public bool hasNoMove = false;

    public static MainController instance;

    public int Score
    {
        get { return Prefs.CurrentScore; }
        set {
            Prefs.CurrentScore = value;
            scoreText.text = value.ToString();
            UpdateProgress();
            if (value >= fullScore) OnComplete();
        }
    }

    public void TouchWatchAds()
    {
        string videoAdid = VideData.Instance.GetVide();
        TTSDK.TTRewardedVideoAd r = AdMgr.Instance.ShowVideoAdNew(videoAdid);
        Score += 10;
        //创建激励视频关闭回调
        r.OnClose += (bol, val) =>
        {
            Debug.Log("关闭广告 ，是否已经看完" + bol);
            //看完广告获得提示
            if (bol)
            {
                Score += 10;
                MaidianNew.MaidianBackCallback(" ");
                Debug.Log("广告看完");
            }
            else
            {
                Debug.Log("广告未看完");
            }
        };

        //创建报错回调  
        r.OnError += (code, errorMessage) =>
        {

            Debug.Log("code:" + code + "错误信息：" + errorMessage);
        };

        //展示广告（新版本必须调用，不然无法展示出来广告）
        r.Show();

    }

    public int CurrentLevel
    {
        get { return Prefs.CurrentLevel; }
        set {
            Prefs.CurrentLevel = value;
            currentLevelText.text = value.ToString();
            nextLevelText.text = (value + 1).ToString();
        }
    }

    public bool IsSoundEnabled
    {
        get { return Prefs.IsSoundEnabled; }
        set {
            Prefs.IsSoundEnabled = value;
            soundIcon.sprite = value ? soundOn : soundOff;
            soundIconHome.sprite = value ? soundOn : soundOff;
        }
    }

    public bool IsVibrateEnabled
    {
        get { return Prefs.IsVibrateEnabled; }
        set
        {
            Prefs.IsVibrateEnabled = value;
            vibrateIcon.sprite = value ? vibrateOn : vibrateOff;
            vibrateIconHome.sprite = value ? vibrateOn : vibrateOff;
        }
    }

    protected override void Awake()
    {
        base.Awake();
        instance = this;
        Application.targetFrameRate = 60;
    }

    protected override void Start()
    {
        base.Start();
        fullScore = GetFullScore();
        Score = Prefs.CurrentScore;
        CurrentLevel = Prefs.CurrentLevel;
        IsSoundEnabled = Prefs.IsSoundEnabled;
        IsVibrateEnabled = Prefs.IsVibrateEnabled;
        currentSliceSprite = sliceCollection[Prefs.CurrentSliceItem];
        Prefs.SetSliceUnlocked(0, true);

        circle1.color = progressColor;
        progressImage.color = progressColor;
        
        Invoke("AddEvent", 0.5f);
        CreateSliceCollection();

        Timer.Schedule(this, 0.3f, ShowSliceUI);
    }

    private void ShowSliceUI()
    {
        string json = Prefs.SavedData;
        if (string.IsNullOrEmpty(json))
        {
            currentTurn = GetNewTurn();
            nextTurn = GetNewTurn();
        }
        else
        {
            var savedData = JsonUtility.FromJson<SavedData>(json);
            currentTurn = savedData.currentTurn;
            nextTurn = savedData.nextTurn;

            int i = 0;
            var slotDatas = savedData.slotDatas;
            foreach (var slot in slots)
            {
                slot.SetData(slotDatas[i].sliceDatas);
                i++;
            }
        }

        ShowTurn();
    }

    private void AddEvent()
    {
        //AdmobController.instance.rewardBasedVideo.OnAdRewarded += HandleRewardBasedVideoRewarded;
        //AdmobController.instance.rewardBasedVideo.OnAdClosed += HandleRewardBasedVideoClosed;
    }

    public void HandleRewardBasedVideoClosed(object sender, System.EventArgs args)
    {
        Timer.Schedule(this, 0.3f, () =>
        {
            if (continueClick && continueObj.activeSelf)
            {
                clockCoroutine = StartCoroutine(IEClock());
            }

            continueClick = false;
            sliceItemClickToUnlock = false;
        });
    }

    private void CreateSliceCollection()
    {
        int i = 0;
        foreach(var sprite in sliceCollection)
        {
            var item = Instantiate(collectionItemPrefab, collectionScrollRect.content.transform);
            item.transform.localScale = Vector3.one;

            UpdateSliceItemUI(i);

            var sliceTr = item.transform.Find("Slice");
            sliceTr.GetComponent<Image>().sprite = sprite;

            int _tempInt = i;
            item.GetComponent<Button>().onClick.AddListener(() => OnCollectionItemClick(_tempInt));
            i++;
        }
    }

    private void UpdateSliceItemUI(int index)
    {
        var item = collectionScrollRect.content.transform.GetChild(index);
        bool isUnlocked = Prefs.IsSliceUnlocked(index);

        var adIcon = item.transform.Find("AdIcon");
        var watchAdRemainder = item.transform.Find("WatchAdRemainder");
        var sliceTr = item.transform.Find("Slice");

        sliceTr.gameObject.SetActive(isUnlocked);
        watchAdRemainder.gameObject.SetActive(!isUnlocked);
        adIcon.gameObject.SetActive(!isUnlocked);

        if (!isUnlocked)
        {
            Text remainderText = watchAdRemainder.GetComponent<Text>();
            remainderText.text = Prefs.NumAdRemainder(index).ToString();
        }
    }

    public void OnCollectionItemClick(int index)
    {
        bool isUnlocked = Prefs.IsSliceUnlocked(index);
        if (isUnlocked)
        {
            OnCollectionBackClick();
            ChangeCurrentSliceSprite(index);
        }
        else
        {
            //if (AdmobController.instance.rewardBasedVideo.IsLoaded())
            //{
                //sliceItemClickToUnlock = true;
                //sliceItemIndexClickToUnlock = index;

//                AdmobController.instance.ShowRewardBasedVideo();
//#if UNITY_EDITOR
//                Toast.instance.ShowMessage("You are watching rewarded video ad", 3);
//                Timer.Schedule(this, 4f, () =>
//                {
//                    HandleRewardBasedVideoRewarded(null, null);
//                });
//#endif
//            }
//            else
//            {
//                Toast.instance.ShowMessage("Ad is not available at the moment");
//            }
        }
    }

    private void ChangeCurrentSliceSprite(int index)
    {
        Prefs.CurrentSliceItem = index;
        currentSliceSprite = sliceCollection[index];
        foreach (var slot in slots)
        {
            slot.SetSliceSprite(currentSliceSprite);
        }

        currentSlice.SetSprite(currentSliceSprite);
    }

    //public void HandleRewardBasedVideoRewarded(object sender)
    //{
    //    if (continueClick)
    //    {
    //        continueClick = false;
    //        OnVideoRewarded();
    //    }
    //    else if (sliceItemClickToUnlock)
    //    {
    //        int sliceIndex = sliceItemIndexClickToUnlock;
    //        int adRemainder = Prefs.NumAdRemainder(sliceIndex);
    //        adRemainder--;
    //        Prefs.SetNumAdRemainder(sliceIndex, adRemainder);
    //        if (adRemainder == 0)
    //        {
    //            Prefs.SetSliceUnlocked(sliceIndex, true);
    //        }

    //        UpdateSliceItemUI(sliceIndex);
    //        sliceItemClickToUnlock = false;
    //    }
    //}

    public void NextTurn()
    {
        nextSlice.transform.DOScale(Vector3.zero, 0.3f);
        Destroy(nextSlice.gameObject, 0.3f);

        currentTurn = nextTurn;
        nextTurn = GetNewTurn();

        ShowTurn();

        if (!HasMove(currentTurn))
        {
            OutofMove();
        }
    }

    private void ShowTurn()
    {
        currentSlice = Instantiate(slicePrefabs[(int)currentTurn.type], centerTr);
        currentSlice.transform.localScale = Vector3.zero;
        currentSlice.ApplyAngle(currentTurn.angle);
        currentSlice.SetSprite(currentSliceSprite);

        nextSlice = Instantiate(comingSlicePrefabs[(int)nextTurn.type], comingUpTr);
        nextSlice.transform.localScale = Vector3.one * 0.8f;
        nextSlice.transform.localRotation = Quaternion.Euler(0, 0, nextTurn.angle * 60);
        nextSlice.transform.position = comingUpTr.position + Vector3.right * 2;
        nextSlice.angle = nextTurn.angle;

        nextSlice.transform.DOMove(comingUpTr.position, 0.3f);
    }

    private Turn GetNewTurn()
    {
        List<int> numInts = Enumerable.Range(0, 5).ToList();
        CUtils.Shuffle(numInts);
        
        if (UnityEngine.Random.value > 0.97f)
        {
            for(int i = 0; i < numInts.Count; i++)
            {
                Turn turn = new Turn() { type = Slice.Type.Slice3, angle = numInts[i] };
                if (HasMove(turn)) return turn;
            }
        }

        if (UnityEngine.Random.value <= 0.94f && UnityEngine.Random.value > 0.92f)
        {
            for (int i = 0; i < numInts.Count; i++)
            {
                Turn turn = new Turn() { type = Slice.Type.Slice2, angle = numInts[i] };
                if (HasMove(turn)) return turn;
            }
        }

        int value = UnityEngine.Random.Range(0, 6);
        Turn aTurn = new Turn() { type = Slice.Type.Slice1, angle = value };
        return aTurn;
    }

    public bool HasMove(Turn aTurn)
    {
        foreach(var slot in slots)
        {
            if (slot.HasMove(aTurn)) return true;
        }
        return false;
    }

    private void UpdateProgress()
    {
        progressImage.fillAmount = (float)Score / fullScore;
    }

    public void OnComplete()
    {
        circle2.color = progressColor;

        levelCompleteObj.SetActive(true);
        var textTr = levelCompleteObj.transform.Find("Text");
        textTr.localScale = Vector3.zero;
        textTr.DOScale(Vector3.one, 0.5f).SetEase(textEase);

        Timer.Schedule(this, 1f, () =>
        {
            CUtils.ShowInterstitialAd();
            levelCompleteObj.SetActive(false);
            CurrentLevel++;

            SetupNewGame();
            if ((CurrentLevel - 1) % GameConfig.instance.unlockSliceInEvery_xx_Level == 0)
            {
                int lockedSlice = GetLockedSlice();
                if (lockedSlice != -1)
                {
                    justUnlockedSlice = lockedSlice;
                    Prefs.SetSliceUnlocked(justUnlockedSlice, true);
                    UpdateSliceItemUI(justUnlockedSlice);
                    ShowSliceUnlockedScene();
                }
            }
        });

        Prefs.SavedData = null;
    }

    private int GetLockedSlice()
    {
        for(int i = 0; i < sliceCollection.Length; i++)
        {
            if (Prefs.IsSliceUnlocked(i) == false) return i;
        }
        return -1;
    }

    private Coroutine clockCoroutine;
    public void OutofMove()
    {
        hasNoMove = true;
        outofMoveObj.SetActive(true);
        var textTr = outofMoveObj.transform.Find("Text");
        textTr.localScale = Vector3.zero;
        textTr.DOScale(Vector3.one, 0.5f).SetEase(textEase);

        Timer.Schedule(this, 0.8f, () =>
        {
            outofMoveObj.SetActive(false);
            //ShowContinueScreen();
            //clockTime = CLOCK_FULL_TIME;
            //continueText.color = continueTextFrom;
            //clockCoroutine = StartCoroutine(IEClock());

            //CUtils.ShowInterstitialAd();

            //AdmobController.instance.rewardBasedVideo.IsLoaded() && 
            if (numWatchAdToContinue < GameConfig.instance.maxWatchAdToContinue)
            {
                ShowContinueScreen();
                clockTime = CLOCK_FULL_TIME;
                continueText.color = continueTextFrom;
                clockCoroutine = StartCoroutine(IEClock());
            }
            else
            {
                SetupNewGame();
            }
        });
    }

    private IEnumerator IEClock()
    {
        while (clockTime > 0)
        {
            clockTime -= Time.deltaTime;
            clockImage.fillAmount = clockTime / CLOCK_FULL_TIME;
            continueText.color = Color.Lerp(continueTextTo, continueTextFrom, clockTime / CLOCK_FULL_TIME);
            yield return new WaitForEndOfFrame();
        }

        CloseContinueScreen();
        SetupNewGame();
    }

    public void OnContinue()
    {
        if (continueClick)
        {
            continueClick = false;
            OnVideoRewarded();
        }
        else if (sliceItemClickToUnlock)
        {
            int sliceIndex = sliceItemIndexClickToUnlock;
            int adRemainder = Prefs.NumAdRemainder(sliceIndex);
            adRemainder--;
            Prefs.SetNumAdRemainder(sliceIndex, adRemainder);
            if (adRemainder == 0)
            {
                Prefs.SetSliceUnlocked(sliceIndex, true);
            }

            UpdateSliceItemUI(sliceIndex);
            sliceItemClickToUnlock = false;
        }
        //if (clockTime <= 0) return;

        //        if (AdmobController.instance.rewardBasedVideo.IsLoaded())
        //        {
        //            StopCoroutine(clockCoroutine);
        //            continueClick = true;
        //            numWatchAdToContinue++;

        //            AdmobController.instance.ShowRewardBasedVideo();
        //#if UNITY_EDITOR
        //            Toast.instance.ShowMessage("You are watching rewarded video ad", 3);
        //            Timer.Schedule(this, 4f, () =>
        //            {
        //                HandleRewardBasedVideoRewarded(null, null);
        //            });
        //#endif
        //        }
        //        else
        //        {
        //            SetupNewGame();
        //        }

        string videoAdid = VideData.Instance.GetVide();
        TTSDK.TTRewardedVideoAd r = AdMgr.Instance.ShowVideoAdNew(videoAdid);
        //创建激励视频关闭回调
        r.OnClose += (bol, val) =>
        {
            UnityEngine.Debug.Log("关闭广告 ，是否已经看完" + bol);
            //看完广告获得提示
            if (bol)
            {
                StopCoroutine(clockCoroutine);
                continueClick = true;

                MaidianNew.MaidianBackCallback(" ");
                UnityEngine.Debug.Log("广告看完");
            }
            else
            {
                SetupNewGame();
                UnityEngine.Debug.Log("广告未看完");
            }
        };

        //创建报错回调  
        r.OnError += (code, errorMessage) =>
        {
            SetupNewGame();
            UnityEngine.Debug.Log("code: " + code + " 错误信息: " + errorMessage);

        };

        //展示广告（新版本必须调用，不然无法展示出来广告）
        r.Show();
    }

    private void OnVideoRewarded()
    {
        CloseContinueScreen();
        Timer.Schedule(this, 0.35f, () =>
        {
            hasNoMove = false;
            foreach (var slot in slots)
            {
                slot.Explode();
            }

            PlayExplosion();
            HeavyVibration();
        });
    }

    public void OnPauseClick()
    {
        CUtils.ShowInterstitialAd();

        pauseScreenObj.SetActive(true);
        pauseScreenObj.GetComponent<CanvasGroup>().alpha = 0;
        DOTween.To(x => pauseScreenObj.GetComponent<CanvasGroup>().alpha = x, 0, 1, 0.3f);

        PlayButton();
    }

    public void OnPauseClose()
    {
        DOTween.To(x => pauseScreenObj.GetComponent<CanvasGroup>().alpha = x, 1, 0, 0.3f).OnComplete(() =>
        {
            pauseScreenObj.SetActive(false);
        });

        PlayButton();
    }

    public void OnToggleSound()
    {
        IsSoundEnabled = !IsSoundEnabled;
        PlayButton();
    }

    public void OnToggleVibrate()
    {
        IsVibrateEnabled = !IsVibrateEnabled;
        PlayButton();
    }

    public void OnPlayHomeClick()
    {
        DOTween.To(x => homeScreenObj.GetComponent<CanvasGroup>().alpha = x, 1, 0, 0.3f).OnComplete(() =>
        {
            homeScreenObj.SetActive(false);
        });

        PlayButton();
    }

    public void OnHomeClick()
    {
        homeScreenObj.SetActive(true);
        pauseScreenObj.SetActive(false);
        homeScreenObj.GetComponent<CanvasGroup>().alpha = 0;
        DOTween.To(x => homeScreenObj.GetComponent<CanvasGroup>().alpha = x, 0, 1, 0.3f);

        PlayButton();
    }

    public void ShowContinueScreen()
    {
        //修改为重新开始
        OnReplayClick();
        //continueObj.SetActive(true);
        //continueObj.GetComponent<CanvasGroup>().alpha = 0;
        //DOTween.To(x => continueObj.GetComponent<CanvasGroup>().alpha = x, 0, 1, 0.3f);
    }

    public void CloseContinueScreen()
    {
        DOTween.To(x => continueObj.GetComponent<CanvasGroup>().alpha = x, 1, 0, 0.3f).OnComplete(()=>
        {
            continueObj.SetActive(false);
        });
    }

    public void OnRateClick()
    {
        CUtils.OpenStore();
        PlayButton();
    }

    public void OnReplayClick()
    {
        pauseScreenObj.SetActive(false);
        SetupNewGame();
        PlayButton();
    }

    public void OnCollectionBackClick()
    {
        DOTween.To(x => collectionScreen.GetComponent<CanvasGroup>().alpha = x, 1, 0, 0.3f).OnComplete(() =>
       {
           collectionScreen.SetActive(false);
       });
        PlayButton();
    }

    public void OnCollectionButtonClick()
    {
        collectionScreen.SetActive(true);
        CUtils.ShowInterstitialAd();

        collectionScreen.GetComponent<CanvasGroup>().alpha = 0;
        DOTween.To(x => collectionScreen.GetComponent<CanvasGroup>().alpha = x, 0, 1, 0.3f);

        PlayButton();
    }

    public void ShowSliceUnlockedScene()
    {
        sliceUnlockedScene.SetActive(true);
        var sliceImage = sliceUnlockedScene.transform.Find("SliceImage");
        sliceImage.GetComponent<Image>().sprite = sliceCollection[justUnlockedSlice];
        var canvasGroup = sliceUnlockedScene.GetComponent<CanvasGroup>();

        canvasGroup.alpha = 0;
        DOTween.To(x => canvasGroup.alpha = x, 0, 1, 0.3f);
    }

    public void CloseSliceUnlockedScene()
    {
        DOTween.To(x => sliceUnlockedScene.GetComponent<CanvasGroup>().alpha = x, 1, 0, 0.3f).OnComplete(() =>
        {
            sliceUnlockedScene.SetActive(false);
        });
    }

    public void OnUseItClick()
    {
        ChangeCurrentSliceSprite(justUnlockedSlice);
        CloseSliceUnlockedScene();
        PlayButton();
    }

    public void OnLaterClick()
    {
        CloseSliceUnlockedScene();
        PlayButton();
    }

    public void HeavyVibration()
    {
        if (!Prefs.IsVibrateEnabled) return;
        MMVibrationManager.Haptic(HapticTypes.HeavyImpact);
    }

    public void LightVibration()
    {
        if (!Prefs.IsVibrateEnabled) return;
        MMVibrationManager.Haptic(HapticTypes.LightImpact);
    }

    public void PlayAddToSlot()
    {
        if (!Prefs.IsSoundEnabled) return;
        audioSource.PlayOneShot(addToSlotClip);
    }

    public void PlayExplosion()
    {
        if (!Prefs.IsSoundEnabled) return;
        audioSource.PlayOneShot(explosionClip);
    }

    public void PlayButton()
    {
        if (!Prefs.IsSoundEnabled) return;
        audioSource.PlayOneShot(buttonClip);
    }

    public void SetupNewGame()
    {
        fullScore = GetFullScore();
        Score = 0;
        hasNoMove = false;
        numWatchAdToContinue = 0;

        foreach (var slot in slots)
        {
            slot.Clear();
        }

        Destroy(currentSlice.gameObject);
        Destroy(nextSlice.gameObject);

        currentTurn = GetNewTurn();
        nextTurn = GetNewTurn();
        ShowTurn();
    }

    private int GetFullScore()
    {
        return (int)(GameConfig.instance.baseScore * Mathf.Pow(1.2f, Prefs.CurrentLevel - 1));
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.O))
        {
            OutofMove();
        }

        if (Input.GetKeyDown(KeyCode.Q))
        {
            OnQuitGame();
        }

        if (Input.GetKeyDown(KeyCode.U))
        {
            ShowSliceUnlockedScene();
        }

        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit();
        }
    }

    private void OnApplicationQuit()
    {
        OnQuitGame();
    }

    private void OnQuitGame()
    {
        if (hasNoMove)
        {
            Score = 0;
            Prefs.SavedData = null;
            return;
        }

        List<SlotData> slotDatas = new List<SlotData>();
        foreach(var slot in slots)
        {
            List<SliceData> sliceDatas = new List<SliceData>();
            foreach(var slice in slot.slices)
            {
                var sliceScript = slice.GetComponent<Slice>();
                SliceData sliceData = new SliceData() { type = sliceScript.type, angle = sliceScript.angle };
                sliceDatas.Add(sliceData);
            }

            var slotData = new SlotData() { sliceDatas = sliceDatas };
            slotDatas.Add(slotData);
        }

        var savedData = new SavedData() { currentTurn = currentTurn, nextTurn = nextTurn, slotDatas = slotDatas };
        var json = JsonUtility.ToJson(savedData);
        Prefs.SavedData = json;
    }
}

[System.Serializable]
public class Turn
{
    public Slice.Type type;
    public int angle;
}

[System.Serializable]
public class SliceData
{
    public Slice.Type type;
    public int angle;
}

[System.Serializable]
public class SlotData
{
    public List<SliceData> sliceDatas;
}

[System.Serializable]
public class SavedData
{
    public Turn currentTurn;
    public Turn nextTurn;
    public List<SlotData> slotDatas;
}